import config from '../../focus.config.js';
import http from './http.js';
import queue from './queue.js';
import showToast from './showToast.js';
import { showLoading, hideLoading } from './loading.js';
import toJson from '../data/toJson.js';
import runtimeType from '../sys/runtimeType.js';

/**
 * download资源下载【异步方法】
 * @description download资源下载，参数详情请查看配置文件focus.config.js
 * @param {Object} parameter 方法参数
 */
function download(parameter) {
	
	// ------------------------------------------------ 参数预处理
    // 获取当前运行环境
    var runType = runtimeType();
	// 获取配置文件download信息
	var config_download = config.download;
	// 合并方法参数
	var paramLast = Object.assign({}, config_download, parameter);
	// 成品请求地址 = 请求地址头 + api地址
	if (paramLast["openHttphead"] == true) { paramLast["url"] = http('get') + paramLast["url"]; }
	
	// ------------------------------------------------ 绿色通道判定
	// 是否允许请求通过
	var isCanReq = false;
	// 绿色通道直接请求
	if (paramLast["openGreen"] == true) { isCanReq = true; }
	else {
		// 队列不拥挤也可请求
		isCanReq = queue('add', paramLast["url"]);
		// 如果是拥挤状态，报错提醒
		if (isCanReq != true)
		{
			// 错误信息对象
			var err_back = { code: 400, data: null, msg: '该接口正在请求中，请稍候' };
			// 进行错误提示
			showToast(paramLast, err_back.msg);
            // 配置文件失败方法
            if (config_download && config_download.fail) { config_download.fail(err_back); }
            // 主动参数的失败方法
            if (parameter && parameter.fail) { parameter.fail(err_back); }
		}
	}
	
	// ------------------------------------------------ 下载方法调用
	// 允许状态，才执行
	if (isCanReq == true)
	{
		// ------------------------------------------------ header请求头
		// 要传递请求头 编辑
		var req_header = {};
        // 1. 配置文件header加入到此数据
        if (config_download["header"]) { for (var key in config_download["header"]) { req_header[key] = config_download.header[key]; } }
        // 2. 主动传递参数的header覆盖到此数据
        if (paramLast["header"]) { for (var key in paramLast["header"]) { req_header[key] = paramLast.header[key]; } }
		/** 添加token鉴权
		 * 数据示例：{ "Authorization": 'Bearer ' + 'AD7TGQW98WQFW-D273D87-238G' }
		 * */
		
		// ------------------------------------------------ 地址栏传输数据
		// 请求地址取出
		var str_url_api = paramLast["url"];
		// 地址栏数据添加
		for (let key in paramLast["urlData"]) { str_url_api += '/' + encodeURIComponent(paramLast.urlData[key]); }
		
        // ------------------------------------------------ 调用下载请求api
		// 如果是“非UNI”环境
		if (runType == 'nonUNI')
        {
            // 获取当前本地的域名
            var str_host_local = window.location.host;
            // 要下载文件的地址域名
            var reg_host = /(\w+):\/\/([^\/:]+)(:\d*)?([^# ]*)/;
            var str_host_download = str_url_api.match(reg_host)[2];
            // 如果是同源文件下载
            if (str_host_local == str_host_download)
            {
                // 创建节点id
                var str_dom_id = '__focus_network__download_a__';
                // 创建一个a节点
                var dom_a = document.createElement("a");
                dom_a.setAttribute('id', str_dom_id); // 节点id赋值
                dom_a.setAttribute('href', str_url_api); // 文件下载地址赋值
                dom_a.setAttribute('download', str_url_api); // 文件下载名称赋值
                dom_a.style.display = 'none'; // 元素设置为隐藏
                // 将a标签dom对象添加到页面中
                document.body.appendChild(dom_a);
                // 触发点击事件
                dom_a.click();
                // 销毁a标签dom元素
                dom_a.parentNode.removeChild(dom_a);
            }
            // 非同源文件下载
            else {
                // 初次显示"下载中"提示弹框
                showLoading(paramLast, 0);
                
                // 创建 XMLHttpRequest 对象
                let xmlhttp = {};
                if (window.XMLHttpRequest) { xmlhttp = new XMLHttpRequest(); }
                else { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); }
                
                // 超时限制
                var timeout = setTimeout(()=>{
                    // 终止请求
                	xmlhttp.abort();
                    // 清除地址缓存
                    queue('del', paramLast["url"]);
                    // 组装返回数据
                	var data_back = { code: 408, data: {}, msg: "请求超时" };
                    // 取消loading弹框
                    hideLoading(paramLast);
                    // 显示提示框
                    showToast(paramLast, data_back.msg);
                    // 配置文件失败方法
                    if (config_download && config_download.fail) { config_download.fail(data_back); }
                    // 主动参数的失败方法
                    if (parameter && parameter.fail) { parameter.fail(data_back); }
                }, paramLast["timeout"]);
                
                // 下载进度回调
                xmlhttp.onprogress = (ev) => {
                	// 检测是否真实上传
                	if (ev.lengthComputable) 
                	{
                        // 此文件上传进度 赋值
                        var num_progress_file = Math.floor(ev.loaded / ev.total * 1000) / 10; // 百分比，如： 53.8
                        // 传回给监听方法的数据
                        var backThis = {
                        	total: ev.total, // 数据总的长度
                        	downloaded: ev.loaded, // 已经下载的数据长度
                        	percentage: num_progress_file // 进度百分比
                        };
                        // 进度显示框
                        showLoading(paramLast, backThis.percentage);
                        // 配置文件监听回调
                        if (config_download && config_download.progress) { config_download.progress(backThis); }
                        // 主动参数的监听回调
                        if (parameter && parameter.progress) { parameter.progress(backThis); }
                	}
                };
                
                // 请求设置
                xmlhttp.open("GET", str_url_api, true); // 请求方式和地址
                for (var k in req_header) { xmlhttp.setRequestHeader(k, req_header[k]); } // 请求头数据赋值
                xmlhttp.responseType = 'blob'; // 指定xmlhttp获取到数据的数据类型
                
                // 服务器响应
                xmlhttp.onreadystatechange = () => {
                	// 链接接口成功
                	if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
                	{
                        // 取消超时限制
                        if (timeout) { clearTimeout(timeout); }
                        // 接收结果数据
                        var str_url_blob = xmlhttp.response ? xmlhttp.response : null;
                        // 使用获取到的blob对象创建的url
                        if (str_url_blob) { str_url_blob = window.URL.createObjectURL(str_url_blob); }
                        // 封装回调数据
                        var data_return = { tempFilePath: str_url_blob };
                		// 清除地址缓存
                        queue('del', paramLast["url"]);
                        // 取消loading弹框
                        hideLoading(paramLast);
                        // 如果数据转换失败了
                        if (!data_return.tempFilePath)
                        {
                            // 错误提示
                            showToast(paramLast, '返回数据格式错误');
                            // 配置文件失败方法
                            if (config_download && config_download.fail) { config_download.fail(data_return); }
                            // 主动参数的失败方法
                            if (parameter && parameter.fail) { parameter.fail(data_return); }
                        }
                        // 成功回调
                        else {
                            // 创建节点id
                            var str_dom_id = '__focus_network__download_a__';
                            // 创建一个a节点
                            var dom_a = document.createElement("a");
                            dom_a.setAttribute('id', str_dom_id); // 节点id赋值
                            dom_a.setAttribute('href', data_return.tempFilePath); // 文件下载地址赋值
                            dom_a.setAttribute('download', data_return.tempFilePath); // 文件下载名称赋值
                            dom_a.style.display = 'none'; // 元素设置为隐藏
                            // 将a标签dom对象添加到页面中
                            document.body.appendChild(dom_a);
                            // 触发点击事件
                            dom_a.click();
                            // 销毁a标签dom元素
                            dom_a.parentNode.removeChild(dom_a);
                            // 配置文件成功方法
                            if (config_download && config_download.success) { config_download.success(data_return); }
                            // 主动参数的成功方法
                            if (parameter && parameter.success) { parameter.success(data_return); }
                        }
                    }
                	// 链接接口失败
                	else if (xmlhttp.readyState == 4)
                	{
                		// 取消超时限制
                		if (timeout) { clearTimeout(timeout); }
                		// 组装返回数据
                		var resD = {
                		    code: xmlhttp.status ? xmlhttp.status : 400,
                		    data: null,
                		    msg: xmlhttp.responseText ? xmlhttp.responseText : null,
                		};
                        // 清除地址缓存
                        queue('del', paramLast["url"]);
                        // 取消loading弹框
                        hideLoading(paramLast);
                        // 错误提示
                        showToast(paramLast, '抱歉，数据请求异常 ' + resD.code);
                        // 配置文件失败方法
                        if (config_download && config_download.fail) { config_download.fail(resD); }
                        // 主动参数的失败方法
                        if (parameter && parameter.fail) { parameter.fail(resD); }
                	}
                };
                
                // 发送请求
                xmlhttp.send();
            }
        }
        // 如果是UNI环境
        else {
            // 初次显示"下载中"提示弹框
            showLoading(paramLast, 0);
            // 官方发起下载api
            let downloadTask = uni.downloadFile({
            	url: str_url_api,
            	header: req_header,
            	timeout: paramLast["timeout"],
            	fail: (resD) => {
            		// 清除地址缓存
            		queue('del', paramLast["url"]);
            		// 取消loading弹框
            		hideLoading(paramLast);
            		// 显示提示框 此处数据为框架系统返回数据，所以是errMsg
            		showToast(paramLast, resD.errMsg);
                    // 配置文件失败方法
                    if (config_download && config_download.fail) { config_download.fail(resD); }
                    // 主动参数的失败方法
                    if (parameter && parameter.fail) { parameter.fail(resD); }
            	},
            	success: (resD) => {
            		// 清除地址缓存
            		queue('del', paramLast["url"]);
            		// 取消loading弹框
            		hideLoading(paramLast);
            		// 如果是状态码错误
            		if (resD.statusCode != 200)
            		{
            			// 错误提示
            			showToast(paramLast, '抱歉，数据请求异常 ' + resD.statusCode);
                        // 配置文件失败方法
                        if (config_download && config_download.fail) { config_download.fail(resD); }
                        // 主动参数的失败方法
                        if (parameter && parameter.fail) { parameter.fail(resD); }
            		}
            		// 成功回调
            		else if (resD.tempFilePath && resD.tempFilePath.length>0)
            		{
                        // 封装回调数据
                        var data_return = { tempFilePath: resD.tempFilePath };
                        // 配置文件成功方法
                        if (config_download && config_download.success) { config_download.success(data_return); }
                        // 主动参数的成功方法
                        if (parameter && parameter.success) { parameter.success(data_return); }
            		}
            		// 如果没有临时文件地址
            		else {
                        // 错误提示
                        showToast(paramLast, '抱歉，临时文件保存异常');
                        // 配置文件失败方法
                        if (config_download && config_download.fail) { config_download.fail(resD); }
                        // 主动参数的失败方法
                        if (parameter && parameter.fail) { parameter.fail(resD); }
                    }
            	},
            });
            // 上传进度监听
            downloadTask.onProgressUpdate((TaskD) => {
            	// 传回给监听方法的数据
            	var backThis = {
            		total: TaskD.totalBytesExpectedToWrite, // 数据总的长度
            		downloaded: TaskD.totalBytesWritten, // 已经下载的数据长度
            		percentage: TaskD.progress // 进度百分比
            	};
            	// 进度显示框
            	showLoading(paramLast, backThis.percentage);
                // 配置文件监听回调
                if (config_download && config_download.progress) { config_download.progress(backThis); }
                // 主动参数的监听回调
                if (parameter && parameter.progress) { parameter.progress(backThis); }
            });
        }
        
	}
	
}

export default download;